<#include "/@inc/funcMacros.ftl">
<#include "/@inc/copyright.txt">
<#assign className = TriaGram + "E" + Prefix + LateType + "Build">
<#assign intfName = TriaGram + "I" + Prefix + LateType>
<#assign baseName = TriaGram + Prefix + LateType >
<@pp.renameOutputFile name=className+".cpp">
</@pp.renameOutputFile>
//===============================================================================
//
// ${className}.cpp
// Provide implementation to interface
//      ${intfName}Build
//===============================================================================
//  ${Month} ${Year}  Creation: Code generated by the CAA wizard  ${Author}
//===============================================================================
// Local Framework
#include "${className}.h"
#include "${TriaGram}${Prefix}${LateType}Algo.h"

// ${TriaGram}${AppName}Interfaces Framework
#include "${intfName}.h"
#include "${TriaGram}UtlMacros.h"

// GeometricObjects Framework
#include "CATGeoFactory.h"

// Mathematics Framework
//#include "CATMathDirection.h"

// MechanicalModeler Framework
#include "CATIMfProcReport.h"
#include "CATMfBRepDefs.h"
#include "CATMfErrUpdate.h"
#include "CATIUpdateError.h"
#include "CATIGeometricalElement.h"

// MecModInterfaces Framework
#include "CATIMechanicalProperties.h"

// ObjectModelerBase Framework
#include "CATLISTV_CATBaseUnknown.h"

// ObjectSpecsModeler Framework
#include "CATIAlias.h"
#include "CATISpecObject.h"

// NewTopologicalObjects Framework
#include "CATBody.h"
#include "CATTopData.h"

// System Framework
#include "CATMsgCatalog.h"
#include "CATListOfCATUnicodeString.h"


// Mathematics Framework
#include "CATSoftwareConfiguration.h"  // Needed to create topological data
#include "CATCGMJournalList.h"
#include "CATCGMJournalInfo.h"

//-----------------------------------------------------------------------------

CATImplementClass ( ${className},
                    DataExtension,
                    CATBaseUnknown,
                    ${TriaGram}${Prefix}${LateType}  );

//-----------------------------------------------------------------------------
#include "TIE_CATIBuild.h"
TIE_CATIBuild( ${className});

//-----------------------------------------------------------------------------
${className}::${className}():
CATBaseUnknown()
{
    _pCGMJournalList = NULL ;
}

//-----------------------------------------------------------------------------
${className}::~${className}()
{
    _pCGMJournalList = NULL ;
}

//-----------------------------------------------------------------------------
HRESULT ${className}::DeactivateOutput (CATBoolean ibIsInActive)
{
    HRESULT rc = E_FAIL ;

	${intfName}_var sp${LateType} = this ;
	CATAssert(NULL_var != sp${LateType}) ;

<#list Attributes as attrib>  <#t>
<#-- Check for sp_OUT spec  -->
<#if attrib.facet == "sp_OUT">
<#switch attrib.type>
<#case "tklist_specobject"><#t>
<#case "tklist_component"><#t>
	CATListValCATISpecObject_var   list${attrib.name} ;
	rc =  sp${LateType}->Get${attrib.name}(list${attrib.name}) ;

    int n${attrib.name} = list${attrib.name}.Size() ;
    for ( int n${attrib.name}Index = 1; n${attrib.name}Index <= n${attrib.name} ; n${attrib.name}Index++)
    {
		rc = Deactivate(list${attrib.name}[n${attrib.name}Index], ibIsInActive) ;
	}

	if(FAILED(rc))
	{
		return rc ;
	}
	<#break>
<#case "tk_specobject"><#t>
<#case "tk_component"><#t>
	CATISpecObject_var   sp${attrib.name} ;
	rc =  sp${LateType}->Get${attrib.name}(sp${attrib.name}) ;
	rc = Deactivate(sp${attrib.name}, ibIsInActive) ;
	if(FAILED(rc))
	{
		return rc ;
	}
<#break>
</#switch>
</#if>
</#list>

 return rc ;
}

//-----------------------------------------------------------------------------
HRESULT ${className}::PreProcess ()
{
    HRESULT rc = S_OK ;

    // -1- Cleaning last update error
    CATIUpdateError_var  		spiUpdateErrorOnThis     = this ;
	if( NULL_var != spiUpdateErrorOnThis)
   {
	  spiUpdateErrorOnThis->UnsetUpdateError();
   }

	${intfName}_var sp${LateType} = this ;
	CATAssert(NULL_var != sp${LateType}) ;

	// If this feature is deactivated then deactive its output topological result.
    CATBoolean bIsInActive = CheckDeactivation(this) ;
	if( TRUE == bIsInActive )
	{
		rc = DeactivateOutput(bIsInActive);
		return E_FAIL ;
	}

	// Check for deactivation of any of the inputs

<#list Attributes as attrib>  <#t>
<#-- Check for sp_IN spec  -->
<#if attrib.facet == "sp_IN">
<#switch attrib.type>
<#case "tk_specobject"><#t>
<#case "tk_component">

	CATISpecObject_var   sp${attrib.name} ;
	rc =  sp${LateType}->Get${attrib.name}(sp${attrib.name}) ;
	bIsInActive = CheckDeactivation(sp${attrib.name}) ;
	if( TRUE == bIsInActive )
	{
		ThrowDeactivationError(sp${attrib.name}) ;
		//return DeactivateOutput(bIsInActive) ;
	}
	<#break>
<#case "tklist_specobject"><#t>
<#case "tklist_component">

	CATISpecObject_var spSpec${attrib.name}Deactivated ;
	CATListValCATISpecObject_var   list${attrib.name} ;
	rc =  sp${LateType}->Get${attrib.name}(list${attrib.name}) ;
	bIsInActive = CheckListDeactivation(list${attrib.name}, spSpec${attrib.name}Deactivated) ;
	if( TRUE == bIsInActive )
	{
		ThrowDeactivationError(spSpec${attrib.name}Deactivated) ;
		//return DeactivateOutput(bIsInActive);
	}
	<#break>
</#switch>
</#if>
</#list>

 return rc ;
}

HRESULT ${className}::Deactivate(CATBaseUnknown * ipSpec, CATBoolean bIsInActive )
{
	CATIMechanicalProperties_var spMechProp = ipSpec ;
	if( NULL_var == spMechProp)
	{
		return E_FAIL ;
	}

	if(bIsInActive)
	{
		spMechProp->InActivate() ;
	}
	else
	{
		spMechProp->Activate() ;
	}

    return (bIsInActive) ? E_FAIL : S_OK ;
}

CATBoolean ${className}::CheckDeactivation(CATBaseUnknown * ipSpec)
{
    CATBoolean bIsInActive = FALSE ;

	CATIMechanicalProperties_var spMechProp = ipSpec ;
	if( NULL_var == spMechProp)
	{
		return bIsInActive;
	}

	if(spMechProp->IsInactive ())
	{
		bIsInActive = TRUE ;
	}

    return bIsInActive ;
}

CATBoolean ${className}::CheckListDeactivation(CATListValCATISpecObject_var & iListSpec, CATISpecObject_var & ospSpecDeactivated)
{
    CATBoolean bIsInActive = FALSE ;

    int nPoints = iListSpec.Size() ;
    for (int i = 1; i <= nPoints ; i++)
    {
        if(CheckDeactivation(iListSpec[i]))
        {
            bIsInActive = TRUE ;
            ospSpecDeactivated = iListSpec[i] ;
            break ;
        }
    }

    return bIsInActive ;
}

void ${className}::ThrowDeactivationError(CATISpecObject * ipSpec)
{
    CATIAlias_var spAlias(ipSpec);
    CATAssert(NULL_var != spAlias);

    CATUnicodeString strFeatureName = spAlias->GetAlias();
    CATUnicodeString strErrorMsg = CATMsgCatalog::BuildMessage( "${baseName}Errors", "DeactivationError",  &strFeatureName, 1);

    CATMfErrUpdate *pError = new CATMfErrUpdate();
    pError->SetDiagnostic(1, strErrorMsg);
    CATThrow(pError);

}

//-----------------------------------------------------------------------------
// -3-1 Filling the lists of the specifications to follow by the procedural report
HRESULT ${className}::CreateProcReport()
{
   ${intfName}_var sp${LateType} = this ;

   int i=0, nSize = 0 ;
   HRESULT rc = E_FAIL ;
   CATLISTV(CATBaseUnknown_var) ListSpec;
   CATListOfCATUnicodeString    ListKeys;
<#list Attributes as attrib>  <#t>
<#-- Check for sp_IN spec  -->
<#if attrib.facet == "sp_IN">
<#switch attrib.type>
<#case "tklist_specobject"><#t>
<#case "tklist_component"><#t>
	CATListValCATISpecObject_var   list${attrib.name} ;
	rc =  sp${LateType}->Get${attrib.name}(list${attrib.name}) ;
	nSize = list${attrib.name}.Size() ;
	for(i =1 ; i <= nSize ; i++)
	{
		 ListSpec.Append( list${attrib.name}[i] );
		 ListKeys.Append( MfKeyNone          );
	}
	<#break>
<#case "tk_specobject"><#t>
<#case "tk_component"><#t>
	CATISpecObject_var   sp${attrib.name} ;
	rc =  sp${LateType}->Get${attrib.name}(sp${attrib.name}) ;
	if( NULL_var != sp${attrib.name})
	{
		 ListSpec.Append( sp${attrib.name});
		 ListKeys.Append( MfKeyNone          );
	}
<#break>
</#switch>
</#if>
</#list>

    CATIMfProcReport_var 		spiProcReport            = this ;
    if ( NULL_var != spiProcReport)
    {
        // Creates the procedural report- the result is associated with the
        // feature itself - so BoolOper is 0             // This method can throw an error
        int BoolOper = 0;
        spiProcReport->CreateProcReport(ListSpec,ListKeys,BoolOper);

        // do not release this pointer	This method can throw an error
        _pCGMJournalList = spiProcReport->GetCGMJournalList();
    }

    return rc ;
}

//-----------------------------------------------------------------------------
HRESULT ${className}::Build ()
{
    HRESULT rc = E_FAIL ;

    CATIUpdateError_var  		spiUpdateErrorOnThis     = this ;
    CATIMfProcReport_var 		spiProcReport            = this ;

    CATTry
    {
		rc = PreProcess();
		if(FAILED(rc))
		{
			return rc ;
		}

		rc = CreateFeatureTopology();
    }
	CATCatch ( CATMfErrUpdate , pUpdateError)
	{
		// Associates the error with the ${LateType}
		if(NULL_var != spiUpdateErrorOnThis)
		{
			spiUpdateErrorOnThis->SetUpdateError(pUpdateError);
		}

		// Deletes the result ( proc report + pResultBody )
		if (NULL_var != spiProcReport)
		{
		   spiProcReport->DeleteProcReport();
		}

		// Re-dispatches the error. In interactive mode, this errror will be caught by CATPrtUpdateCom
		CATRethrow ;
	}
	CATCatch ( CATError , pError)
	{
		CATMfErrUpdate *pErrorToThrow = new CATMfErrUpdate();
		pErrorToThrow->SetDiagnostic(1,pError->GetNLSMessage());

		::Flush(pError);

		// Associates the error with the feature
		if(NULL_var != spiUpdateErrorOnThis)
		{
			spiUpdateErrorOnThis->SetUpdateError(pErrorToThrow);
		}

		 // Deletes the result ( proc report + pResultBody )
		if (NULL_var != spiProcReport)
		{
		   spiProcReport->DeleteProcReport();
		}

		CATThrow(pErrorToThrow);
	}
    CATEndTry

    return rc ;
}


//-----------------------------------------------------------------------------
// Create the CATBody Result of the feature
HRESULT ${className}::CreateFeatureTopology( )
{
    HRESULT rc = E_FAIL ;

	// Creating the procedural report
	rc = CreateProcReport();
	if(FAILED(rc))
	{
		return rc ;
	}

    CATIMfProcReport_var   spMfProcReport = this ;
    CATAssert(NULL_var != spMfProcReport) ;

    CATGeoFactory_var  spiGeomFactory;
    rc = spMfProcReport->GetGeoFactoryFromFeature(spiGeomFactory) ;

    CATSoftwareConfiguration * pSoftConfig   =  new CATSoftwareConfiguration();   // release pointer after procedural report ending

    CATTopData TopData(pSoftConfig, _pCGMJournalList) ;

    CATISpecObject_var spSpecOnThis = this ;
    CATBody   *pResultBody = NULL ;
    ${TriaGram}${ Prefix}${LateType}Algo algo(spSpecOnThis, spiGeomFactory, &TopData) ;
    rc = algo.Create${LateType}(pResultBody) ;
    if ( FAILED(rc) || (NULL == pResultBody)  )
    {
        ${TriaGram}UtlReleasePtr(pSoftConfig) ;

        // Ensure that pError is NOT NULL
        CATError *pError =  CATError::CATGetLastError(rc) ; 
		CATAssert(pError) ; // This MUST NOT be NULL. Added for mkChkSrc
        CATUnicodeString strDiagnostic = pError->GetNLSMessage() ; // For Debug

        CATThrow(pError);
    }

    CATCGMJournalList* pLocalJournal = WriteProcReport(pResultBody, pSoftConfig);
    if(NULL != pLocalJournal && NULL != _pCGMJournalList)
    {
        _pCGMJournalList->InsertJournal(pLocalJournal);
    }

    int nBoolOper = 1 ;  // same as CreateProcReport
    // This method can throw an error
    spMfProcReport->StoreProcReport(pResultBody, NoCopy, nBoolOper);
    ${TriaGram}UtlReleasePtr(pSoftConfig) ;

    return rc ;
}


CATCGMJournalList* ${className}::WriteProcReport(CATBody* ipBody,CATSoftwareConfiguration* ipSoftConfig)
{
	if(NULL == ipBody)
	{
		return NULL ;
	}

	// Tailor this function to your actual needs. This MAY or MAYNOT be needed.
	CATCGMJournalList *pLocalJournal = new CATCGMJournalList(ipSoftConfig, NULL);

	CATLISTP (CATGeometry) operands ;
	int nCount = 0, i = 0;

	<#if (OutputBodyDimension > 1) >
	CATLISTP(CATCell) listOfFaces;
	ipBody->GetAllCells(listOfFaces, 2);
	int numberOfFaces = listOfFaces.Size();
	for(i = 1; i<= numberOfFaces; i++)
	{
		CATCGMJournalInfo *pInfo = new CATCGMJournalInfo(++nCount);
		pLocalJournal->ReportCreation(operands, (CATGeometry*)(listOfFaces[i]), pInfo);
	}
	</#if>

	<#if (OutputBodyDimension > 0) >
	CATLISTP(CATCell) listOfEdges;
	ipBody->GetAllCells(listOfEdges, 1);
	int numberOfEdges = listOfEdges.Size();
	for(i = 1; i<= numberOfEdges; i++)
	{
		CATCGMJournalInfo *pInfo = new CATCGMJournalInfo(++nCount);
		pLocalJournal->ReportCreation(operands, (CATGeometry*)(listOfEdges[i]), pInfo);
	}
	</#if>

	<#if (OutputBodyDimension > -1) >
	CATLISTP(CATCell) listOfVertices;
	ipBody->GetAllCells(listOfVertices,0);
	int numberOfVertices = listOfVertices.Size();
	for(i = 1; i<= numberOfVertices; i++)
	{
		CATCGMJournalInfo *pInfo = new CATCGMJournalInfo(++nCount);
		pLocalJournal->ReportCreation(operands, (CATGeometry*)(listOfVertices[i]), pInfo);

	}
	</#if>

	pLocalJournal->Tass();

	return pLocalJournal;
}

